
package com.hlkj.pay.gateway.profit.impl;
/*
 * Hlpay-Plus aggregate payment system.
 * Copyright (c) 2024-2025 Hlpay Team Copyright has the right of final interpretation.
 */

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import com.hlkj.framework.common.pojo.CommonResult;
import com.hlkj.framework.extension.executor.ExtensionExecutor;
import com.hlkj.framework.extension.scenario.BizScenario;
import com.hlkj.pay.app.merchant.ext.ChannelMerchantProfitAccountExtPt;
import com.hlkj.pay.app.merchant.ext.dto.profit.ChannelProfitAccountBindContext;
import com.hlkj.pay.app.merchant.ext.dto.profit.ChannelProfitAccountContext;
import com.hlkj.pay.dto.merchant.access.MerchantAccessResDto;
import com.hlkj.pay.dto.merchant.fund.MerchantFundAccountBindDto;
import com.hlkj.pay.dto.merchant.fund.MerchantFundAccountDto;
import com.hlkj.pay.dto.merchant.fund.ProfitAccountResultDto;
import com.hlkj.pay.enums.PayEnums;
import com.hlkj.pay.gateway.profit.IChannelProfitAccountGateway;
import com.hlkj.pay.infrastructure.model.merchant.MerchantAppChannelDO;
import com.hlkj.pay.infrastructure.model.merchant.fund.MerchantFundAccountBindDO;
import com.hlkj.pay.infrastructure.model.pay.PayChannelRequestDO;
import com.hlkj.pay.service.merchant.IMerchantApplicationService;
import com.hlkj.pay.service.pay.IPayChannelService;
import com.hlkj.pay.service.pay.IProviderService;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

/**
 * 分润账号
 * 
 * @author HlpayTeam
 * @date 2024/11/07 11:04
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class ChannelProfitAccountGatewayImpl implements IChannelProfitAccountGateway {

    @Value("${hlkj.pay.barrier:false}")
    private boolean barrier;

    @Value("${hlkj.pay.test:false}")
    private boolean test;

    @Value("${hlkj.domain}")
    private String domain;

    private final ExtensionExecutor extensionExecutor;

    private final IMerchantApplicationService merchantApplicationService;

    private final IProviderService providerService;

    private final IPayChannelService payChannelService;

    @Override
    public boolean extensionExist(String channelCode) {
        return extensionExecutor.executeExist(ChannelMerchantProfitAccountExtPt.class, BizScenario.valueOf(channelCode));
    }

    @Override
    public CommonResult<ProfitAccountResultDto> submitProfitAccount(MerchantFundAccountDto merchantFundAccountDto) {
        ProfitAccountResultDto profitAccountResultDto = new ProfitAccountResultDto();
        if (barrier) {
            log.info("测试环境提交分账账号直接返回成功 requestId:{}", merchantFundAccountDto.getMerchantFundAccount().getRequestId());
            return CommonResult.success(profitAccountResultDto);
        }
        MerchantAppChannelDO merchantAppChannelDO = merchantApplicationService.queryAppChannelDetail(merchantFundAccountDto.getMerchantFundAccount().getMchChannelCode());
        ChannelProfitAccountContext channelProfitAccountContext = new ChannelProfitAccountContext();
        channelProfitAccountContext.setMerchantAppChannelDO(merchantAppChannelDO);
        channelProfitAccountContext.setMerchantFundAccountDto(merchantFundAccountDto);
        channelProfitAccountContext.setProviderChannelConfig(providerService.queryConfig(merchantAppChannelDO.getProviderCode(), merchantAppChannelDO.getChannelCode()));
        channelProfitAccountContext.setTest(test);
        extensionExecutor.executeVoid(ChannelMerchantProfitAccountExtPt.class, BizScenario.valueOf(merchantAppChannelDO.getChannelCode()),
                ex -> ex.submitProfitAccount(channelProfitAccountContext));
        PayChannelRequestDO payChannelRequestDO = channelProfitAccountContext.getPayChannelRequest();
        MerchantAccessResDto merchantAccessResDto = new MerchantAccessResDto();
        if (payChannelRequestDO != null) {
            payChannelRequestDO.setRelationId(merchantFundAccountDto.getMerchantFundAccount().getRequestId());
            payChannelRequestDO.setSn(payChannelRequestDO.getSn());
            payChannelRequestDO.setChannelCode(merchantAppChannelDO.getChannelCode());
            payChannelRequestDO.setProviderCode(merchantAppChannelDO.getProviderCode());
            payChannelRequestDO.setMchChannelCode(merchantAppChannelDO.getCode());
            payChannelService.saveRequestLocal(payChannelRequestDO, PayEnums.CHANNEL_REQUEST_TYPE.FUND_ACCOUNT);
            merchantAccessResDto.setApplyNo(payChannelRequestDO.getApplyNo());
        }
        if (channelProfitAccountContext.isProcessStatus()) {
            profitAccountResultDto.setAccountNo(channelProfitAccountContext.getAccountNo());
            return CommonResult.success(profitAccountResultDto);
        }
        else {
            return CommonResult.error(1, channelProfitAccountContext.getRemark());
        }
    }

    @Override
    public CommonResult<ProfitAccountResultDto> updateProfitAccount(MerchantFundAccountDto merchantFundAccountDto) {
        ProfitAccountResultDto profitAccountResultDto = new ProfitAccountResultDto();
        if (barrier) {
            log.info("测试环境修改分账账号直接返回成功 requestId:{}", merchantFundAccountDto.getMerchantFundAccount().getRequestId());
            return CommonResult.success(profitAccountResultDto);
        }
        MerchantAppChannelDO merchantAppChannelDO = merchantApplicationService.queryAppChannelDetail(merchantFundAccountDto.getMerchantFundAccount().getMchChannelCode());
        ChannelProfitAccountContext channelProfitAccountContext = new ChannelProfitAccountContext();
        channelProfitAccountContext.setMerchantAppChannelDO(merchantAppChannelDO);
        channelProfitAccountContext.setMerchantFundAccountDto(merchantFundAccountDto);
        channelProfitAccountContext.setProviderChannelConfig(providerService.queryConfig(merchantAppChannelDO.getProviderCode(), merchantAppChannelDO.getChannelCode()));
        channelProfitAccountContext.setTest(test);
        extensionExecutor.executeVoid(ChannelMerchantProfitAccountExtPt.class, BizScenario.valueOf(merchantAppChannelDO.getChannelCode()),
                ex -> ex.updateProfitAccount(channelProfitAccountContext));
        PayChannelRequestDO payChannelRequestDO = channelProfitAccountContext.getPayChannelRequest();
        if (payChannelRequestDO != null) {
            payChannelRequestDO.setRelationId(merchantFundAccountDto.getMerchantFundAccount().getRequestId());
            payChannelRequestDO.setSn(payChannelRequestDO.getSn());
            payChannelRequestDO.setChannelCode(merchantAppChannelDO.getChannelCode());
            payChannelRequestDO.setProviderCode(merchantAppChannelDO.getProviderCode());
            payChannelRequestDO.setMchChannelCode(merchantAppChannelDO.getCode());
            payChannelService.saveRequestLocal(payChannelRequestDO, PayEnums.CHANNEL_REQUEST_TYPE.FUND_ACCOUNT);
        }
        if (channelProfitAccountContext.isProcessStatus()) {
            profitAccountResultDto.setAccountNo(channelProfitAccountContext.getAccountNo());
            return CommonResult.success(profitAccountResultDto);
        }
        else {
            return CommonResult.error(1, channelProfitAccountContext.getRemark());
        }
    }

    @Override
    public CommonResult<ProfitAccountResultDto> bindProfitAccount(MerchantFundAccountBindDto merchantFundAccountBindDto) {
        ProfitAccountResultDto profitAccountResultDto = new ProfitAccountResultDto();
        MerchantFundAccountBindDO merchantFundAccountBindDO = merchantFundAccountBindDto.getMerchantFundAccountBindDO();
        if (barrier) {
            log.info("测试环境提交分账账号绑定直接返回成功 fundAccountId:{}", merchantFundAccountBindDO.getAccountNo());
            return CommonResult.success(profitAccountResultDto);
        }
        MerchantAppChannelDO merchantAppChannelDO = merchantFundAccountBindDto.getMerchantAppChannelDO();
        ChannelProfitAccountBindContext channelProfitAccountContext = new ChannelProfitAccountBindContext();
        channelProfitAccountContext.setMerchantAppChannelDO(merchantAppChannelDO);
        channelProfitAccountContext.setMerchantFundAccountBindDto(merchantFundAccountBindDto);
        channelProfitAccountContext.setProviderChannelConfig(providerService.queryConfig(merchantAppChannelDO.getProviderCode(), merchantAppChannelDO.getChannelCode()));
        channelProfitAccountContext.setTest(test);
        extensionExecutor.executeVoid(ChannelMerchantProfitAccountExtPt.class, BizScenario.valueOf(merchantAppChannelDO.getChannelCode()),
                ex -> ex.bindProfitAccount(channelProfitAccountContext));
        PayChannelRequestDO payChannelRequestDO = channelProfitAccountContext.getPayChannelRequest();
        if (payChannelRequestDO != null) {
            payChannelRequestDO.setRelationId(merchantFundAccountBindDO.getAccountNo());
            payChannelRequestDO.setSn(payChannelRequestDO.getSn());
            payChannelRequestDO.setChannelCode(merchantAppChannelDO.getChannelCode());
            payChannelRequestDO.setProviderCode(merchantAppChannelDO.getProviderCode());
            payChannelRequestDO.setMchChannelCode(merchantAppChannelDO.getCode());
            payChannelService.saveRequestLocal(payChannelRequestDO, PayEnums.CHANNEL_REQUEST_TYPE.FUND_ACCOUNT);
        }
        if (!channelProfitAccountContext.isProcessStatus()) {
            return CommonResult.error(1, channelProfitAccountContext.getRemark());
        }
        return CommonResult.success(profitAccountResultDto);
    }

    @Override
    public CommonResult<ProfitAccountResultDto> unBindProfitAccount(MerchantFundAccountBindDto merchantFundAccountBindDto) {
        ProfitAccountResultDto profitAccountResultDto = new ProfitAccountResultDto();
        MerchantFundAccountBindDO merchantFundAccountBindDO = merchantFundAccountBindDto.getMerchantFundAccountBindDO();
        if (barrier) {
            log.info("测试环境提交分账账号解除绑定直接返回成功 fundAccountId:{}", merchantFundAccountBindDO.getAccountNo());
            return CommonResult.success(profitAccountResultDto);
        }
        MerchantAppChannelDO merchantAppChannelDO = merchantFundAccountBindDto.getMerchantAppChannelDO();
        ChannelProfitAccountBindContext channelProfitAccountContext = new ChannelProfitAccountBindContext();
        channelProfitAccountContext.setMerchantAppChannelDO(merchantAppChannelDO);
        channelProfitAccountContext.setMerchantFundAccountBindDto(merchantFundAccountBindDto);
        channelProfitAccountContext.setProviderChannelConfig(providerService.queryConfig(merchantAppChannelDO.getProviderCode(), merchantAppChannelDO.getChannelCode()));
        channelProfitAccountContext.setTest(test);
        extensionExecutor.executeVoid(ChannelMerchantProfitAccountExtPt.class, BizScenario.valueOf(merchantAppChannelDO.getChannelCode()),
                ex -> ex.unBindProfitAccount(channelProfitAccountContext));
        PayChannelRequestDO payChannelRequestDO = channelProfitAccountContext.getPayChannelRequest();
        if (payChannelRequestDO != null) {
            payChannelRequestDO.setRelationId(merchantFundAccountBindDO.getAccountNo());
            payChannelRequestDO.setSn(payChannelRequestDO.getSn());
            payChannelRequestDO.setChannelCode(merchantAppChannelDO.getChannelCode());
            payChannelRequestDO.setProviderCode(merchantAppChannelDO.getProviderCode());
            payChannelRequestDO.setMchChannelCode(merchantAppChannelDO.getCode());
            payChannelService.saveRequestLocal(payChannelRequestDO, PayEnums.CHANNEL_REQUEST_TYPE.FUND_ACCOUNT);
        }
        if (!channelProfitAccountContext.isProcessStatus()) {
            return CommonResult.error(1, channelProfitAccountContext.getRemark());
        }
        return CommonResult.success(profitAccountResultDto);
    }

    @Override
    public void queryAccountBindList(String mchChannelCode) {
        if (barrier) {
            log.info("测试环境提交分账账号解除绑定直接返回成功 fundAccountId:{}", mchChannelCode);
            return;
        }
        MerchantAppChannelDO merchantAppChannelDO = merchantApplicationService.queryAppChannelDetail(mchChannelCode);
        if (!extensionExist(merchantAppChannelDO.getChannelCode())) {
            return;
        }
        ChannelProfitAccountBindContext channelProfitAccountContext = new ChannelProfitAccountBindContext();
        channelProfitAccountContext.setMerchantAppChannelDO(merchantAppChannelDO);
        channelProfitAccountContext.setProviderChannelConfig(providerService.queryConfig(merchantAppChannelDO.getProviderCode(), merchantAppChannelDO.getChannelCode()));
        channelProfitAccountContext.setTest(test);
        extensionExecutor.executeVoid(ChannelMerchantProfitAccountExtPt.class, BizScenario.valueOf(merchantAppChannelDO.getChannelCode()),
                ex -> ex.queryAccountBindList(channelProfitAccountContext));
    }
}
